package org.linlinjava.litemall.wx;

import java.util.HashMap;
import java.util.Map;
import java.util.Random;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReadWriteLock;
import java.util.concurrent.locks.ReentrantReadWriteLock;

/**
 * 用ReadWriteLock读写锁来实现一个高效的Map缓存
 *
 * @author zhy
 * @create 2018-11-18 13:47
 **/
public class ReadAndWriteLock<K, V> {
	private final ReadWriteLock lock = new ReentrantReadWriteLock();

	private final Lock readLock = lock.readLock();

	private final Lock writeLock = lock.writeLock();

	private final Map<K, V> map;

	public ReadAndWriteLock(Map<K, V> map) {
		this.map = map;
	}

	/*使用tryLock()方法写*/
	public V put(K key, V value) {
		writeLock.lock();
		try {
			System.out.println("put" + key + "value" + value);
			return map.put(key, value);
		}
		finally {
			writeLock.unlock();
		}
	}

	public V get(K key) {
		readLock.lock();
		try {
			V value = map.get(key);
			System.out.println("get" + key + "" + value);
			return value;
		}
		finally {
			readLock.unlock();
		}
	}

	public static void main(String[] args) {
		final ReadAndWriteLock<String, Integer> rw = new ReadAndWriteLock(new HashMap());
		ExecutorService executorService = Executors.newCachedThreadPool();
		for (int i = 0; i < 20; i++) {
			executorService.execute(new TestRunnable(rw));
		}
		executorService.shutdown();
	}

	static class TestRunnable implements Runnable {
		private final ReadAndWriteLock<String, Integer> rw;

		private final String KEY = "X";

		public TestRunnable(ReadAndWriteLock<String, Integer> rw) {
			this.rw = rw;
		}

		@Override
		public void run() {
			Random random = new Random();
			int r = random.nextInt(100);
			if (r < 40) {
				rw.put(KEY, r);
			} else {
				rw.get(KEY);
			}

		}
	}
}
